/* AminoView.m - Copyright 1993  Steve Ludtke */
/* This view currently just displays protein molecular weights and */
/* helical wheel diagrams. More may happen in future releases */

/* This view is so simple that I don't think I'll comment it ... */

#import "Mtypes.h"
#import "AminoView.h"
#import "MolObj.h"
#import <ctype.h>

/* Table of 20 common amino acids */
ACID acid[AADEF] = {
{ "X","UNK","Unknown",0,2,		-1,-1,-1,-1 },
{ "A","Ala","Alanine",89,2,		1,0,0,0 },
{ "V","Val","Valine",117,3,		3,0,0,0 },
{ "L","Leu","Leucine",131,3,	4,0,0,0 },
{ "I","Ile","Isoleucine",131,3,	4,0,0,0 },
{ "P","Pro","Proline",115,2,	3,0,0,0 },
{ "F","Phe","Phenylalanine",165,3,	7,0,0,0 },
{ "W","Trp","Tryptophan",204,2,	9,0,0,1 },
{ "M","Met","Methionine",149,3,	3,1,0,0 },
{ "G","Gly","Glycine",75,2,		0,0,0,0 },
{ "S","Ser","Serine",105,2,		1,0,1,0 },
{ "T","Thr","Threonine",119,2,	2,0,2,0 },
{ "C","Cys","Cysteine",121,2,	1,1,0,0 },
{ "Y","Tyr","Tyrosine",181,2,	7,0,1,0 },
{ "N","Asn","Asparagine",132,1,	2,0,1,1 },
{ "Q","Gln","Glutamine",146,1,	3,0,1,1 },
{ "D","Asp","Aspartic Acid",133,1, 2,0,2,0 },
{ "E","Glu","Glutamic Acid",147,1, 3,0,2,0 },
{ "K","Lys","Lysine",146,1,		4,0,0,1 },
{ "R","Arg","Arginine",174,1,	4,0,0,3 },
{ "H","His","Histidine",155,1,	4,0,0,2 }
};

@implementation AminoView

-initFrame:(NXRect *)myrect
{
[super initFrame:myrect];
[self setDrawSize:2.0 :2.0];
[self setDrawOrigin:-1.0 :-1.0];

fCir=0;
fAmb=fPho=1;
AR=100.0;

return self;
}

- superviewSizeChanged:(const NXSize *)oldsize
{
[super superviewSizeChanged:oldsize];

[self setDrawSize:2.0 :2.0*frame.size.height/frame.size.width];
[self setDrawOrigin:-1.0 :-1.0];
return self;
}

- setSequence:sender
{
int i,k;

strcpy(seq,[sender stringValue]);
seql=strlen(seq);
seqmw=0;

if (seql>MAXSEQ) {
	seql=0;
	[sender setStringValue:"Max. seq len exceeded"];
	return self;
}

for (i=0; i<seql; i++) {
	seq[i]=toupper(seq[i]);
	for (k=0; k<AADEF; k++) if (seq[i]==acid[k].d1[0]) break;
	if (k==AADEF) seq[i]=tolower(seq[i]);
	seqa[i]=k;
	seqmw+=acid[k].wt-18;
}
seq[seql]=0;

[sender setStringValue:seq];
[self display];
[seqlD setIntValue:seql];
[seqmwD setIntValue:seqmw];
return self;
}

- setSeqStr:sender :(char *)str;
{
int i,k;

strcpy(seq,str);
seql=strlen(seq);
seqmw=0;

if (seql>MAXSEQ) {
	seql=0;
	[seqStr setStringValue:"Max. seq len exceeded"];
	return self;
}

for (i=0; i<seql; i++) {
	seq[i]=toupper(seq[i]);
	for (k=0; k<AADEF; k++) if (seq[i]==acid[k].d1[0]) break;
	if (k==AADEF) seq[i]=tolower(seq[i]);
	seqa[i]=k;
	seqmw+=acid[k].wt-18;
}
seq[seql]=0;

[seqStr setStringValue:seq];
[self display];
[seqlD setIntValue:seql];
[seqmwD setIntValue:seqmw];
return self;
}

-drawSelf:(NXRect *)rects :(int)rectCount
{
int i;
float r,t;
char s[10];

PSsetgray(1.0);
NXRectFill(&bounds);

PSsetsma();
PSsetlinewidth(0.008);
s[1]=0;

if (fCir) {
	PSsetgray(.66667);
	PSmoveto(.30,0.0);
	PSarc(0.0,0.0,.30,0.0,360.0);

	PSmoveto(.55,0.0);
	PSarc(0.0,0.0,.55,0.0,360.0);

	PSmoveto(.80,0.0);
	PSarc(0.0,0.0,.80,0.0,360.0);
	
	PSstroke();
}

PSsetgray(0.0);
for (i=0; i<seql; i++) {
	if (seqa[i]==AADEF) continue;
	t=(float) i*AR*DRC;
	r=(float)acid[seqa[i]].phob/4.0;
	if (!fAmb && r==.5) continue;
	if (!fPho) r= 1.0-r;
	s[0]=acid[seqa[i]].d1[0];
	PSmoveto(0.0,0.0);
	PSlineto(r*cos(t),r*sin(t));
	PSstroke();
	r+=.05;	
	PSsetgray(1.0);
	PSmoveto(r*cos(t)+.05,r*sin(t));
	PSarc(r*cos(t),r*sin(t),.05,0.0,360.0);
	PSfill();
	PSsetgray(0.0);
	PSmoveto(r*cos(t)+.05,r*sin(t));
	PSarc(r*cos(t),r*sin(t),.05,0.0,360.0);
	PSmoveto(r*cos(t)-.025,r*sin(t)-.025);
	PSshow(s);
	PSstroke();
}
return self;
}

- dumpEPS:sender
{
static id savePanel=nil;
NXStream *out;

if (!savePanel) {
    savePanel=[SavePanel new];
    [savePanel setRequiredFileType:"eps"];
}

if([savePanel runModal]){
	out=NXOpenMemory(NULL,0, NX_WRITEONLY);
	[self copyPSCodeInside:&bounds to:out];
	NXSaveToFile(out,[savePanel filename]);
	NXCloseMemory(out,NX_FREEBUFFER);
}
return self;
}

- setCircles:sender
{
if ([sender intValue]) fCir=1;
else fCir=0;
[self display];

return self;
}

- setAmbiv:sender
{
if ([sender intValue]) fAmb=1;
else fAmb=0;
[self display];

return self;
}

- setPhobicOut:sender
{
if ([sender intValue]) fPho=1;
else fPho=0;
[self display];

return self;
}

-setAR:sender
{
AR=[sender floatValue];
[self display];
return self;
}
@end
